﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Windows.Data;
using System.Windows.Input;
using System.Xml;
using CaptchaLearning.Infrastructure;
using CaptchaLearning.Recognize;
using CaptchaLearning.Setting;
using CaptchaLearning.Trainning;

namespace CaptchaLearning
{
    public class MainWindowViewModel : WorkspaceViewModel
    {
        #region Fields and Properties

        /// <summary>
        /// Description: Tabpage được bind với list workspaces model
        /// Created by: Nam Mai
        /// Created date: 10/28/2012
        /// </summary>
        ObservableCollection<WorkspaceViewModel> _workspaces;
        public ObservableCollection<WorkspaceViewModel> Workspaces
        {
            get
            {
                if (_workspaces == null)
                {
                    _workspaces = new ObservableCollection<WorkspaceViewModel>();
                    _workspaces.CollectionChanged += this.OnWorkspacesChanged;
                }
                return _workspaces;
            }
        }

        #endregion // Fields and Properties

        public MainWindowViewModel()
        {
            this._trainningCommand = new DelegateCommand(new Action(ExecuteTrainningCommand), () => true);
            this._recognizeCommand = new DelegateCommand(new Action(ExecuteRecognizeCommand), () => true);
            this._settingCommand = new DelegateCommand(new Action(ExecuteSettingCommand), () => true);
            Global.CurrentProject = new Infrastructure.Model.Project();
            LoadCharacterSupportList();
            LoadCharactersForProject(Global.Characters);
        }
        

        #region Commands

        /// <summary>
        /// Description: Open tab Trainning
        /// Created by: Nam Mai
        /// Created date: 10/28/2012
        /// </summary>
        private ICommand _trainningCommand;
        public ICommand TrainningCommand { get { return _trainningCommand; } }
        public void ExecuteTrainningCommand()
        {
            if (ActiveWorkspace(1))
                return;
            TrainningViewModel workspace = new TrainningViewModel();
            Workspaces.Add(workspace);
            this.SetActiveWorkspace(workspace);
        }

        /// <summary>
        /// Description: Open tab Recognition
        /// Created by: Nam Mai
        /// Created date: 10/28/2012
        /// </summary>
        private ICommand _recognizeCommand;
        public ICommand RecognizeCommand { get { return _recognizeCommand; } }
        public void ExecuteRecognizeCommand()
        {
            if (ActiveWorkspace(2))
                return;
            RecognizeViewModel workspace = new RecognizeViewModel();
            Workspaces.Add(workspace);
            this.SetActiveWorkspace(workspace);
        }

        /// <summary>
        /// Description: Open tab Recognition
        /// Created by: Nam Mai
        /// Created date: 10/28/2012
        /// </summary>
        private ICommand _settingCommand;
        public ICommand SettingCommand { get { return _settingCommand; } }
        public void ExecuteSettingCommand()
        {
            if (ActiveWorkspace(3))
                return;
            SettingViewModel workspace = new SettingViewModel();
            Workspaces.Add(workspace);
            this.SetActiveWorkspace(workspace);

        }
        #endregion // Commands

        #region Workspace Event

        /// <summary>
        /// Description: Nếu workspace đã được thoát thì add thêm vô rồi active nó
        /// Created by: Nam Mai
        /// Created date: 10/28/2012
        /// </summary>
        public void SetActiveWorkspace(WorkspaceViewModel workspace)
        {
            bool found = false;
            foreach (WorkspaceViewModel item in this.Workspaces)
            {
                if (item == workspace)
                {
                    found = true;
                }
            }
            if (!found)
                this.Workspaces.Add(workspace);

            ICollectionView collectionView = CollectionViewSource.GetDefaultView(this.Workspaces);
            if (collectionView != null)
                collectionView.MoveCurrentTo(workspace);
        }

        /// <summary>
        /// Description: Các sự kiện thay đổi và yêu cầu thoát của workspace trong tabpage
        /// Created by: Nam Mai
        /// Created date: 10/28/2012
        /// </summary>
        void OnWorkspacesChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.NewItems)
                    workspace.RequestClose += this.OnWorkspaceRequestClose;

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.OldItems)
                    workspace.RequestClose -= this.OnWorkspaceRequestClose;
        }
        void OnWorkspaceRequestClose(object sender, EventArgs e)
        {
            WorkspaceViewModel workspace = sender as WorkspaceViewModel;
            this.Workspaces.Remove(workspace);
        }

        #endregion // Workspace Event

        #region Helpers

        /// <summary>
        /// Load danh sách ký tự supported
        /// </summary>
        private void LoadCharacterSupportList()
        {
            Global.Characters = new ObservableCollection<string>();
            try
            {
                string path = "CaptchaLearning.Resources.Data.Characters.xml";
                Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(path);

                if (stream == null)
                {
                    throw new MissingManifestResourceException("Could not load character list: " + path);
                }
                XmlTextReader reader = new XmlTextReader(stream);

                while (reader.Read())
                {
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        if (reader.Name == "character")
                        {
                            reader.Read();
                            Global.Characters.Add(reader.Value);
                        }
                    }
                }
                reader.Close();
            }
            catch (Exception) { }
        }

        /// <summary>
        /// Load danh sách model ký tự mặc định cho project hiện hành
        /// </summary>
        private void LoadCharactersForProject(ObservableCollection<string> characters)
        {
            Global.CurrentProject.Characters = new ObservableCollection<Infrastructure.Model.Character>();
            foreach (string item in characters)
            {
                Infrastructure.Model.Character c = new Infrastructure.Model.Character();
                c.Id = Guid.NewGuid();
                c.Name = item;
                c.Observations = new ObservableCollection<Infrastructure.Model.ImageColumn>();
                c.Pi = new ObservableCollection<double>();
                c.States = new ObservableCollection<Infrastructure.Model.ImageColumn>();
                c.TransitionMatrix = new Infrastructure.Model.TransitionMatrix();
                c.EmissionMatrix = new Infrastructure.Model.EmissionMatrix();

                Global.CurrentProject.Characters.Add(c);
            }
        }

        /// <summary>
        /// Description: If workspace opened, active it. Type = 1 => trainning, 2 => recog
        /// Created by: Nam Mai
        /// Created date: 10/28/2012
        /// </summary>
        private bool ActiveWorkspace(int type)
        {
            if (type == 1)
            {
                foreach (WorkspaceViewModel item in Workspaces)
                {
                    TrainningViewModel tmp = item as TrainningViewModel;
                    if (tmp != null)
                    {
                        SetActiveWorkspace(item);
                        return true;
                    }
                }
            }
            else if (type == 2)
            {
                foreach (WorkspaceViewModel item in Workspaces)
                {
                    RecognizeViewModel tmp = item as RecognizeViewModel;
                    if (tmp != null)
                    {
                        SetActiveWorkspace(item);
                        return true;
                    }
                }
            }
            return false;
        }

        #endregion // Helpers
    }
}
